package com.eastfair.certificate.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperCacheServiceImpl;
import com.eastfair.cache.certificate.CertificateIndexCacheKeyBuilder;
import com.eastfair.cache.certificate.CertificateUserCacheKeyBuilder;
import com.eastfair.certificate.dao.CertificateIndexMapper;
import com.eastfair.certificate.dto.CertificateDTO;
import com.eastfair.certificate.dto.CertificateIndexDTO;
import com.eastfair.certificate.dto.CertificateUserDTO;
import com.eastfair.certificate.entity.Certificate;
import com.eastfair.certificate.entity.CertificateAuth;
import com.eastfair.certificate.entity.CertificateIndex;
import com.eastfair.certificate.entity.CertificateUser;
import com.eastfair.certificate.exceptioncode.CertificateExceptionCode;
import com.eastfair.certificate.service.CertificateIndexService;
import com.eastfair.boot.service.SuperServiceImpl;

import com.eastfair.certificate.vo.CertificateIndexVO;
import com.eastfair.certificate.vo.CertificateUserVO;
import com.eastfair.certificate.vo.CertificateVO;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.model.CacheKeyBuilder;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.venuebooking.api.ExhibitionManageFeign;
import com.eastfair.venuebooking.vo.ExhibitionSpaceVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;

//import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.aop.framework.AopContext;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.annotation.annotation.cache.Cache;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
//import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 业务实现类
 * 证件指标设置
 * </p>
 *
 * @author ligang
 * @date 2022-07-22
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class CertificateIndexServiceImpl extends SuperCacheServiceImpl<CertificateIndexMapper, CertificateIndex> implements CertificateIndexService {

    @Autowired
    ExhibitionManageFeign exhibitionManageFeign;

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(CertificateIndex model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTeamId(ContextUtil.getTeamId());
        if (model.getUseNumber() == null) {
            model.setUseNumber(0);
        }
        if (model.getConditionNumber() == null) {
            model.setConditionNumber(0);
        }


        //雪花ID
        return R.successDef();
    }

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<CertificateIndex> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }


    @Override
    public IPage<CertificateIndexVO> pageVo(PageParams<CertificateIndexDTO> params) {
        CertificateIndexDTO certificateIndexDTO = params.getModel();
        IPage<CertificateIndex> page = params.buildPage();
        QueryWrapper<CertificateIndex> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(certificateIndexDTO.getCertificateId() != null, CertificateIndex::getCertificateId, certificateIndexDTO.getCertificateId())
                .eq(StringUtils.isNotBlank(certificateIndexDTO.getSpaceCode()), CertificateIndex::getSpaceCode, certificateIndexDTO.getSpaceCode())
                .eq(certificateIndexDTO.getExhibitionId() != null, CertificateIndex::getExhibitionId, certificateIndexDTO.getExhibitionId())
                .eq(certificateIndexDTO.getClassify() != null, CertificateIndex::getClassify, certificateIndexDTO.getClassify())

                .eq(CertificateIndex::getIsDeleted, BusinessConstant.NO);
        //page entity转vo
        IPage<CertificateIndex> certificateIndexIPage = page(page, queryWrapper);
        List<CertificateIndexVO> certificateUserVOList = doToVos(certificateIndexIPage.getRecords());
        if (!CollectionUtil.isEmpty(certificateUserVOList)) {
            assembleData(certificateUserVOList);
        }
        IPage<CertificateIndexVO> certificateIndexVOIPage = ConvertUtil.convertIPage(certificateIndexIPage, certificateUserVOList);
        return certificateIndexVOIPage;
    }

    @Override
    public void assembleData(List<CertificateIndexVO> certificateIndexVOList) {
        //展会信息
        Long exhibitionId = certificateIndexVOList.get(0).getExhibitionId();
        if (exhibitionId != null) {
            R<List<ExhibitionSpaceVO>> listR = exhibitionManageFeign.queryByExhibitionManageId(exhibitionId);
            if (listR.getIsSuccess() && listR.getData() != null && !listR.getData().isEmpty()) {
                for (ExhibitionSpaceVO exhibitionSpaceVO : listR.getData()) {
                    for (CertificateIndexVO certificateIndexVO : certificateIndexVOList) {
                        if (StringUtils.isNotBlank(exhibitionSpaceVO.getSpaceCode()) && exhibitionSpaceVO.getSpaceCode().equals(certificateIndexVO.getSpaceCode())) {
                            certificateIndexVO.setExhibitionSpaceVO(exhibitionSpaceVO);
                        }
                    }
                }
            }
        }
    }


    /**
     * 通用查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
    public List<CertificateIndex> list(CertificateIndexDTO modelDTO, List<Long> ids) {
        return ((CertificateIndexService) AopContext.currentProxy()).listOfCache(modelDTO, ids);
    }


    /**
     * 缓存查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
//    @Cache(key = "",
//            magic = @Magic(
//                    key = "{" +
//                            "{'useNumber', #args[0]?.useNumber}," +
//                            "{'conditionNumber', #args[0]?.conditionNumber}," +
//                            "{'classify', #args[0]?.classify}," +
//                            "{'startTime', #args[0]?.startTime}," +
//                            "{'endTime', #args[0]?.endTime}," +
//                            "{'spaceCode', #args[0]?.spaceCode}," +
//                            "{'certificateId', #args[0]?.certificateId}," +
//                            "{'exhibitionId', #args[0]?.exhibitionId}," +
//                            "{'id', #args[1]}" +
//                            "}"))
    public List<CertificateIndex> listOfCache(CertificateIndexDTO modelDTO, List<Long> ids) {
        //查询
        QueryWrapper<CertificateIndex> queryWrapper = new QueryWrapper<>();
        if (modelDTO != null) {
            queryWrapper.lambda().eq(modelDTO.getUseNumber() != null, CertificateIndex::getUseNumber, modelDTO.getUseNumber());
            queryWrapper.lambda().eq(modelDTO.getConditionNumber() != null, CertificateIndex::getConditionNumber, modelDTO.getConditionNumber());
            queryWrapper.lambda().eq(modelDTO.getClassify() != null, CertificateIndex::getClassify, modelDTO.getClassify());
            queryWrapper.lambda().ge(modelDTO.getStartTime() != null && !"null".equals(modelDTO.getStartTime().toString()), CertificateIndex::getStartTime, modelDTO.getStartTime() != null ? modelDTO.getStartTime().toString() : null);
            queryWrapper.lambda().eq(modelDTO.getStartTimeEq() != null && !"null".equals(modelDTO.getStartTimeEq().toString()), CertificateIndex::getStartTime, modelDTO.getStartTimeEq() != null ? modelDTO.getStartTimeEq().toString() : null);
            queryWrapper.lambda().le(modelDTO.getEndTime() != null && !"null".equals(modelDTO.getEndTime().toString()), CertificateIndex::getEndTime, modelDTO.getEndTime() != null ? modelDTO.getEndTime().toString() : null);
            queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getSpaceCode()), CertificateIndex::getSpaceCode, modelDTO.getSpaceCode());
            queryWrapper.lambda().eq(modelDTO.getCertificateId() != null, CertificateIndex::getCertificateId, modelDTO.getCertificateId());
            queryWrapper.lambda().eq(modelDTO.getExhibitionId() != null, CertificateIndex::getExhibitionId, modelDTO.getExhibitionId());
        }
        if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(CertificateIndex::getId, ids);
        }
        queryWrapper.lambda().eq(CertificateIndex::getIsDeleted, BusinessConstant.DELETE_NO);
        List<CertificateIndex> modelList = list(queryWrapper);
        return modelList;
    }

    public String format(LocalDateTime localDateTime) {
        log.info("localDateTime is {}", localDateTime);
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String timeStr = df.format(localDateTime);
        log.info("timeStr is {}", timeStr);
        return timeStr;
    }


    @Override
    public Boolean verifyIndex(Long certificateId, String spaceCode, LocalDateTime comeTime) {
        CertificateIndexDTO certificateIndexDTO = new CertificateIndexDTO();
        certificateIndexDTO.setCertificateId(certificateId);
        certificateIndexDTO.setSpaceCode(spaceCode);
//        certificateIndexDTO.setStartTime(comeTime);
        certificateIndexDTO.setStartTimeEq(comeTime);
        List<CertificateIndex> certificateIndexList = list(certificateIndexDTO, null);

        /**************由于时区不对，bug完善 start**************/
        if (CollectionUtil.isEmpty(certificateIndexList)) {
            certificateIndexDTO = new CertificateIndexDTO();
            certificateIndexDTO.setCertificateId(certificateId);
            certificateIndexDTO.setSpaceCode(spaceCode);
            //随便取一个
            List<CertificateIndex> certificateIndexList2 = list(certificateIndexDTO, null);
            if (CollectionUtil.isNotEmpty(certificateIndexList2)) {
                certificateIndexList.add(certificateIndexList2.get(0));
            }
        }
        /**************由于时区不对，bug完善 end**************/
        if (certificateIndexList == null || certificateIndexList.isEmpty()) {
            throw BizException.wrap(CertificateExceptionCode.INDEX_NUll);
        }
        for (CertificateIndex certificateIndex : certificateIndexList) {
            if (certificateIndex.getConditionNumber() == null) {
                throw BizException.wrap(CertificateExceptionCode.INDEX_NO);
            }
            if (certificateIndex.getConditionNumber() <= (certificateIndex.getUseNumber() == null ? 0 : certificateIndex.getUseNumber())) {
                throw BizException.wrap(CertificateExceptionCode.INDEX_NO);
            }
        }
        return true;
    }

    @Override
    public Boolean addIndex(Long certificateId, String spaceCode, LocalDateTime comeTime, Integer num) {
        CertificateIndexDTO certificateIndexDTO = new CertificateIndexDTO();
        certificateIndexDTO.setCertificateId(certificateId);
        certificateIndexDTO.setSpaceCode(spaceCode);
        certificateIndexDTO.setStartTime(comeTime);
        List<CertificateIndex> certificateIndexList = list(certificateIndexDTO, null);
        if (CollectionUtil.isNotEmpty(certificateIndexList)) {
            for (CertificateIndex certificateIndex : certificateIndexList) {
                certificateIndex.setUseNumber(certificateIndex.getUseNumber() == null ? Math.max(0, 0 + num) : certificateIndex.getUseNumber() + num);
                updateById(certificateIndex);
            }
        }
        return true;
    }


    /**
     * do转vo
     *
     * @param model model
     * @return modelVo
     */
    @Override
    public CertificateIndexVO doToVo(CertificateIndex model) {
        CertificateIndexVO modelVo = new CertificateIndexVO();
        BeanUtils.copyProperties(model, modelVo);
        modelVo.setId(model.getId());
        return modelVo;
    }

    /**
     * do转vo
     *
     * @param modelList modelList
     * @return list
     */
    @Override
    public List<CertificateIndexVO> doToVos(List<CertificateIndex> modelList) {
        if (modelList == null || modelList.isEmpty()) {
            return null;
        }
        List<CertificateIndexVO> result = new ArrayList<>();
        for (CertificateIndex model : modelList) {
            result.add(doToVo(model));
        }
        return result;
    }

    @Override
    public CacheKeyBuilder getCacheKeyBuilder() {
        return new CertificateIndexCacheKeyBuilder();
    }


    @Override
    public QueryWrapper<CertificateIndex> assembleQueryWrapper(CertificateIndexDTO certificateIndexDTO) {
        QueryWrapper<CertificateIndex> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(certificateIndexDTO.getClassify() != null, CertificateIndex::getClassify, certificateIndexDTO.getClassify())
                .eq(certificateIndexDTO.getCertificateId() != null, CertificateIndex::getCertificateId, certificateIndexDTO.getCertificateId())
                .eq(certificateIndexDTO.getExhibitionId() != null, CertificateIndex::getExhibitionId, certificateIndexDTO.getExhibitionId())
                .le(certificateIndexDTO.getEndTime() != null && !"null".equals(certificateIndexDTO.getEndTime().toString()), CertificateIndex::getEndTime, certificateIndexDTO.getEndTime() != null ? certificateIndexDTO.getEndTime().toString() : null)
                .ge(certificateIndexDTO.getStartTime() != null && !"null".equals(certificateIndexDTO.getStartTime().toString()), CertificateIndex::getStartTime, certificateIndexDTO.getStartTime() != null ? certificateIndexDTO.getStartTime().toString() : null)
                .le(certificateIndexDTO.getStartTimeOfLe() != null && !"null".equals(certificateIndexDTO.getStartTimeOfLe().toString()), CertificateIndex::getStartTime, certificateIndexDTO.getStartTimeOfLe() != null ? certificateIndexDTO.getStartTimeOfLe().toString() : null)
                .ge(certificateIndexDTO.getEndTimeOfGe() != null && !"null".equals(certificateIndexDTO.getEndTimeOfGe().toString()), CertificateIndex::getEndTime, certificateIndexDTO.getEndTimeOfGe() != null ? certificateIndexDTO.getEndTimeOfGe().toString() : null)
                .eq(CertificateIndex::getIsDeleted, BusinessConstant.DELETE_NO);
        return queryWrapper;
    }


}
